/*
 * Formation.cpp
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "Formation.h"
#include "Images.h"
#include "Ship.h"

#include <memory.h>

#define DENSITY     2.5f

void Formation::load(const std::string& data)
{
    clear();
    detect_dimensions(data);

    if (!_cols || !_rows)
        return;

    _units = new Soldier*[_cols * _rows];
    memset(_units, 0, _cols * _rows * sizeof(Soldier*));

    int unit_width  = Images::get(Images::SOLDIER)->w;
    int unit_height = Images::get(Images::SOLDIER)->h;
    double hspacing = unit_width * DENSITY;
    double vspacing = unit_height * DENSITY;
    _width  = (_cols - 1) * hspacing + unit_width;
    _height = (_rows - 1) * vspacing + unit_height;

    int x = 0, y = 0;
    for (unsigned int i = 0; i < data.length(); ++i) 
    {
        switch (data[i])
        {
        case '\n':
            x = 0;
            ++y;
            continue;
        case '\r':
            continue;
        case 's':
            _units[x + y*_cols] = new Soldier(x * hspacing, y * vspacing, _area);
            ++_population;
            break;
        };
        ++x;
    }
}

void Formation::clear()
{
    if (!_units)
        return;

    for (unsigned int i = 0; i < _cols * _rows; ++i)
        delete _units[i];

    _population = 0;
    delete [] _units;
    _units = NULL;
}

void Formation::detect_dimensions(const std::string& data)
{
    _cols = 0;
    _rows = 0;

    if (data.empty())
        return;

    int row_length = 0;
    _rows = 1;

    for (unsigned int i = 0; i < data.length(); ++i) 
    {
        switch (data[i])
        {
        case '\n':
            if (_cols < row_length)
                _cols = row_length;
            row_length = 0;
            ++_rows;
            break;
        case '\r':
            break;
        default:
            ++row_length;
        };
    }

    if (_cols < row_length)
        _cols = row_length;
}

void Formation::update(void* arg)
{
    Ship* ship = reinterpret_cast<Ship*>(arg);
    for (int i = 0; i < _cols * _rows; ++i)
        if (_units[i])
        {
            if (!_units[i]->update(arg))
            {
                delete _units[i];
                _units[i] = NULL;
                --_population;
            }
        }
}

// Delegations here (boring, huh?)

void Formation::blit(SDL_Surface* screen)
{
    for (int i = 0; i < _cols * _rows; ++i)
        if (_units[i])
            _units[i]->blit(screen);
}

void Formation::erase(SDL_Surface* screen, SDL_Surface* background)
{
    for (int i = 0; i < _cols * _rows; ++i)
        if (_units[i])
            _units[i]->erase(screen, background);
}

void Formation::move(int dx, int dy)
{
    for (int i = 0; i < _cols * _rows; ++i)
        if (_units[i])
            _units[i]->move(dx, dy);
}

Soldier* Formation::clean(unsigned int x, unsigned int y)
{
    if (_units[x + y * _cols])
        --_population;

    return _units[x + y * _cols] = NULL;
}

